/*
 * Grid.cpp
 *
 *  Created on: 16/04/2013
 *      Author: gonzalo
 */

#include "Grid.h"

#include "../exceptions/ArgumentInvalidError.h"

void Grid::create_vertex_buffer(GLuint cantidad) {
	if (vertex_buffer != NULL) {
		delete vertex_buffer;
	}
	vertex_buffer_size = 4 * (2 * cantidad + 1);
	vertex_buffer = new GLfloat[vertex_buffer_size * 3];

	int offset;
	float valor;
	for (int i = 0; i < cantidad; i++) {
		offset = 24 * i;
		valor = cantidad;
		vertex_buffer[offset++] = -valor;
		vertex_buffer[offset++] = i + 1;
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = valor;
		vertex_buffer[offset++] = i + 1;
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = -valor;
		vertex_buffer[offset++] = -(i + 1);
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = valor;
		vertex_buffer[offset++] = -(i + 1);
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = i + 1;
		vertex_buffer[offset++] = -valor;
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = i + 1;
		vertex_buffer[offset++] = valor;
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = -(i + 1);
		vertex_buffer[offset++] = -valor;
		vertex_buffer[offset++] = 0;

		vertex_buffer[offset++] = -(i + 1);
		vertex_buffer[offset++] = valor;
		vertex_buffer[offset++] = 0;
	}

	offset = 24 * cantidad;
	valor = cantidad;
	vertex_buffer[offset++] = -valor;
	vertex_buffer[offset++] = 0;
	vertex_buffer[offset++] = 0;

	vertex_buffer[offset++] = valor;
	vertex_buffer[offset++] = 0;
	vertex_buffer[offset++] = 0;

	vertex_buffer[offset++] = 0;
	vertex_buffer[offset++] = -valor;
	vertex_buffer[offset++] = 0;

	vertex_buffer[offset++] = 0;
	vertex_buffer[offset++] = valor;
	vertex_buffer[offset++] = 0;
}

Grid::Grid(GLuint  program, GLuint cantidad) :
		Figure(program) {
	if (cantidad > 1000000) {
		throw ArgumentInvalidError("Grid Error: el argumento cantidad no puede ser mayor a %u\n", cantidad);
	}
	this->create_vertex_buffer(cantidad);
}

Grid::~Grid() {

}

void Grid::draw(GLuint program, glm::mat4 & world_matrix) {
	glm::mat4 matriz = world_matrix * this->model_matrix;

	// Normal Matrix
	glm::mat3 normal_matrix = glm::mat3(1.0f);
	if (this->view_matrix != NULL) {
		glm::mat4 aux = (*this->view_matrix) * world_matrix;
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				normal_matrix[i][j] = aux[i][j];
	}

	// Bind Normal Matrix
	GLuint location_normal_matrix = glGetUniformLocation(program, "NormalMatrix");
	if (location_normal_matrix >= 0) {
		glUniformMatrix3fv(location_normal_matrix, 1, GL_FALSE, &normal_matrix[0][0]);
	}

	// Bind Model Matrix
	GLuint location_model_matrix = glGetUniformLocation(program, "ModelMatrix");
	if (location_model_matrix >= 0) {
		glUniformMatrix4fv(location_model_matrix, 1, GL_FALSE, &matriz[0][0]);
	}

	glEnableClientState(GL_VERTEX_ARRAY);

	glVertexPointer(3, GL_FLOAT, 0, vertex_buffer);

	//glDrawElements(GL_LINES, this->grid_index_buffer_size, GL_UNSIGNED_INT,this->grid_index_buffer);
	glDrawArrays(GL_LINES, 0, this->vertex_buffer_size); // Dibuja desde el primer vertice al ultimo

	glDisableClientState(GL_VERTEX_ARRAY);
}
